
package com.wowoai.common.reponsitory;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import com.wowoai.common.page.Pagination;
import org.springframework.util.Assert;

/**
 * 实现HQL的查询，这里面的方法暂时有可能使用不到
 */
public abstract class BaseDao {
    @PersistenceContext
    private EntityManager entityManager;

    public BaseDao() {
    }

    protected EntityManager getEntityManager() {
        return this.entityManager;
    }

    protected void setParam(Map<String, Object> params, Query query) {
        if (params != null) {
            Iterator var3 = params.entrySet().iterator();

            while(var3.hasNext()) {
                Map.Entry<String, Object> entry = (Map.Entry)var3.next();
                query.setParameter((String)entry.getKey(), entry.getValue());
            }
        }

    }

    protected Query createQuery(String jpql, Object... params) {
        Assert.hasText(jpql, "jpql is not null！");
        Query query = this.entityManager.createQuery(jpql);
        if (params != null) {
            for(int i = 0; i < params.length; ++i) {
                query.setParameter(i, params[i]);
            }
        }

        return query;
    }

    protected Query createNativeQuery(String sql) {
        Assert.hasText(sql, "sql is not null！");
        return this.entityManager.createNativeQuery(sql);
    }

    protected List find(String jpql, Object... params) {
        return this.createQuery(jpql, params).getResultList();
    }

    protected List find(Finder finder) {
        Query query = finder.createQuery(this.entityManager);
        List list = query.getResultList();
        return list;
    }

    protected Object findUnique(String jpql, Object... params) {
        Query query = this.createQuery(jpql, params);
        query.setMaxResults(1);
        return query.getSingleResult();
    }

    protected Object findUnique(Finder finder) {
        Query query = finder.createQuery(this.entityManager);
        query.setMaxResults(1);
        return query.getSingleResult();
    }

    protected int countQueryResult(Finder finder) {
        Query query = this.createQuery(finder.getRowCountJpql());
        finder.setParamsToQuery(query);
        Long totalCount = (Long)query.getSingleResult();
        return totalCount.intValue();
    }

    protected Pagination find(Finder finder, int pageNo, int pageSize) {
        int totalCount = this.countQueryResult(finder);
        return this.find(finder, pageNo, pageSize, totalCount);
    }

    protected List findList(Finder finder, int pageNo, int pageSize) {
        Query query = this.createQuery(finder.getOrigJpql());
        finder.setParamsToQuery(query);
        query.setFirstResult((pageNo - 1) * pageSize);
        query.setMaxResults(pageSize);
        List list = query.getResultList();
        return list;
    }

    protected Pagination find(Finder finder, int pageNo, int pageSize, int totalCount) {
        Pagination p = new Pagination(pageNo, pageSize, totalCount);
        if (totalCount < 1) {
            p.setList(new ArrayList());
            return p;
        } else {
            Query query = this.createQuery(finder.getOrigJpql());
            finder.setParamsToQuery(query);
            query.setFirstResult(p.getFirstResult());
            query.setMaxResults(pageSize);
            List list = query.getResultList();
            p.setList(list);
            return p;
        }
    }

    protected int countSQLQuery(String sql, Map params) {
        sql = sql.replaceAll("(\\{[a-z]+\\.\\*\\},)+", "1,").replaceAll("(\\{[a-z]+\\.\\*\\})", "2");
        Query countSql = this.createNativeQuery("select count(*) from (" + sql + ") countTable ");
        this.setParam(params, countSql);
        BigInteger totalCount = (BigInteger)countSql.getSingleResult();
        return totalCount.intValue();
    }

    protected Pagination sqlQueryPagination(Map<String, Object> params, String sql, Integer pageNO, Integer pageSize) {
        int totalCount = this.countSQLQuery(sql, params);
        return this.sqlQueryPagination(params, sql, pageNO, pageSize, totalCount);
    }

    protected Pagination sqlQueryPagination(Map<String, Object> params, String sql, Integer pageNo, Integer pageSize, Integer totalCount) {
        Pagination p = new Pagination(pageNo, pageSize, totalCount);
        if (totalCount < 1) {
            p.setList(new ArrayList());
            return p;
        } else {
            Query query = this.createNativeQuery(sql);
            query.setFirstResult((pageNo - 1) * pageSize);
            query.setMaxResults(pageSize);
            params.entrySet().forEach((e) -> {
                query.setParameter((String)e.getKey(), e.getValue());
            });
            List list = query.getResultList();
            p.setList(list);
            return p;
        }
    }

    protected Pagination sqlQueryPagination(Map<String, Object> params, String sql, Integer pageNO, Integer pageSize, Class clazz) {
        int totalCount = this.countSQLQuery(sql, params);
        return this.sqlQueryPagination(params, sql, pageNO, pageSize, totalCount, clazz);
    }

    protected Pagination sqlQueryPagination(Map<String, Object> params, String sql, Integer pageNo, Integer pageSize, Integer totalCount, Class clazz) {
        Pagination p = new Pagination(pageNo, pageSize, totalCount);
        if (totalCount < 1) {
            p.setList(new ArrayList());
            return p;
        } else {
            Query query = this.createNativeQuery(sql, clazz);
            query.setFirstResult((pageNo - 1) * pageSize);
            query.setMaxResults(pageSize);
            params.entrySet().forEach((e) -> {
                query.setParameter((String)e.getKey(), e.getValue());
            });
            List list = query.getResultList();
            p.setList(list);
            return p;
        }
    }

    protected Query createNativeQuery(String sql, Class clazz) {
        Assert.hasText(sql, "sql is not null！");
        return this.entityManager.createNativeQuery(sql, clazz);
    }

    protected List nativeSqlQueryList(Map<String, Object> params, String sql, Class clazz) {
        Query query = this.createNativeQuery(sql, clazz);
        params.forEach((key, value) -> {
            query.setParameter(key, value);
        });
        return query.getResultList();
    }
}
